package com.imooc.food.orderservicemanager.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.imooc.food.orderservicemanager.dao.OrderDetailDao;
import com.imooc.food.orderservicemanager.dto.OrderMessageDTO;
import com.imooc.food.orderservicemanager.enummeration.OrderStatus;
import com.imooc.food.orderservicemanager.po.OrderDetailPO;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * 消息处理业务逻辑
 */
@Slf4j
@Service
public class OrderMessageService {

//    @Value("${rabbitmq.exchange}")
//    public String exchangeName;
//    @Value("${rabbitmq.deliveryman-routing-key}")
//    public String deliverymanRoutingKey;
//    @Value("${rabbitmq.settlement-routing-key}")
//    public String settlementRoutingKey;
//    @Value("${rabbitmq.reward-routing-key}")
//    public String rewardRoutingKey;

    @Autowired
    RabbitTemplate rabbitTemplate;
    @Autowired
    private OrderDetailDao orderDetailDao;
    ObjectMapper objectMapper = new ObjectMapper();


    /**
     * 声明队列、交换机、绑定
     *
     * @throws IOException
     * @throws TimeoutException
     * @throws InterruptedException
     */
//    @Async
//    public void handleMessage() throws IOException, TimeoutException, InterruptedException {
//        log.info("start linstening message");
//        ConnectionFactory connectionFactory = new ConnectionFactory();
//        connectionFactory.setHost("localhost");
//        try (Connection connection = connectionFactory.newConnection();
//             Channel channel = connection.createChannel()) {
//
//            /*---------------------restaurant---------------------*/
//            channel.exchangeDeclare(
//                    "exchange.order.restaurant",
//                    BuiltinExchangeType.DIRECT,
//                    true,
//                    false,
//                    null);
//
//            channel.queueDeclare(
//                    "queue.order",
//                    true,
//                    false,
//                    false,
//                    null);
//
//            channel.queueBind(
//                    "queue.order",
//                    "exchange.order.restaurant",
//                    "key.order");
//
//
//            /*---------------------deliveryman---------------------*/
//            channel.exchangeDeclare(
//                    "exchange.order.deliveryman",
//                    BuiltinExchangeType.DIRECT,
//                    true,
//                    false,
//                    null);
//
//
//            channel.queueBind(
//                    "queue.order",
//                    "exchange.order.deliveryman",
//                    "key.order");
//
//            /*---------------------settlement---------------------*/
//
//            channel.exchangeDeclare(
//                    "exchange.settlement.order",
//                    BuiltinExchangeType.FANOUT,
//                    true,
//                    false,
//                    null);
//
//            channel.queueBind(
//                    "queue.order",
//                    "exchange.settlement.order",
//                    "key.order");
//
//            /*---------------------reward---------------------*/
//
//            channel.exchangeDeclare(
//                    "exchange.order.reward",
//                    BuiltinExchangeType.TOPIC,
//                    true,
//                    false,
//                    null);
//
//            channel.queueBind(
//                    "queue.order",
//                    "exchange.order.reward",
//                    "key.order");
//
//            // 启动消费者，监听队列
//            channel.basicConsume("queue.order", true, deliverCallback, consumerTag -> {
//            });
//            // 方法不能退出，因为退出后会关闭连接
//            while (true) {
//                Thread.sleep(100000);
//            }
//        }
//    }


    DeliverCallback deliverCallback = (consumerTag, message) -> {
        String messageBody = new String(message.getBody());
        log.info("deliverCallback:messageBody:{}", messageBody);
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("localhost");
        try {
            OrderMessageDTO orderMessageDTO = objectMapper.readValue(messageBody,
                    OrderMessageDTO.class);
            OrderDetailPO orderPO = orderDetailDao.selectOrder(orderMessageDTO.getOrderId());

            switch (orderPO.getStatus()) {

                case ORDER_CREATING: // 收到商家微服务发来的消息
                    if (orderMessageDTO.getConfirmed() && null != orderMessageDTO.getPrice()) {
                        //更新订单状态，价格
                        orderPO.setStatus(OrderStatus.RESTAURANT_CONFIRMED);
                        orderPO.setPrice(orderMessageDTO.getPrice());
                        orderDetailDao.update(orderPO);
                        try (Connection connection = connectionFactory.newConnection();
                             Channel channel = connection.createChannel()) {
                            String messageToSend = objectMapper.writeValueAsString(orderMessageDTO);
                            channel.basicPublish("exchange.order.deliveryman", "key.deliveryman", null,
                                    messageToSend.getBytes());
                        }
                    } else {
                        orderPO.setStatus(OrderStatus.FAILED);
                        orderDetailDao.update(orderPO);
                    }
                    break;
                case RESTAURANT_CONFIRMED: // 收到骑手微服务发来的消息
                    if (null != orderMessageDTO.getDeliverymanId()) {
                        //更新订单状态，骑手id
                        orderPO.setStatus(OrderStatus.DELIVERYMAN_CONFIRMED);
                        orderPO.setDeliverymanId(orderMessageDTO.getDeliverymanId());
                        orderDetailDao.update(orderPO);
                        try (Connection connection = connectionFactory.newConnection();
                             Channel channel = connection.createChannel()) {
                            String messageToSend = objectMapper.writeValueAsString(orderMessageDTO);
                            channel.basicPublish("exchange.order.settlement", "key.settlement", null,
                                    messageToSend.getBytes());
                        }
                    } else {
                        orderPO.setStatus(OrderStatus.FAILED);
                        orderDetailDao.update(orderPO);
                    }
                    break;
                case DELIVERYMAN_CONFIRMED: // 收到结算微服务发来的消息
                    if (null != orderMessageDTO.getSettlementId()) {
                        //更新订单状态，结算id
                        orderPO.setStatus(OrderStatus.SETTLEMENT_CONFIRMED);
                        orderPO.setSettlementId(orderMessageDTO.getSettlementId());
                        orderDetailDao.update(orderPO);
                        try (Connection connection = connectionFactory.newConnection();
                             Channel channel = connection.createChannel()) {
                            String messageToSend = objectMapper.writeValueAsString(orderMessageDTO);
                            channel.basicPublish("exchange.order.reward", "key.reward", null, messageToSend.getBytes());
                        }
                    } else {
                        orderPO.setStatus(OrderStatus.FAILED);
                        orderDetailDao.update(orderPO);
                    }
                    break;
                case SETTLEMENT_CONFIRMED: // 收到积分微服务发来的消息
                    if (null != orderMessageDTO.getRewardId()) {
                        //更新订单状态，积分id
                        orderPO.setStatus(OrderStatus.ORDER_CREATED);
                        orderPO.setRewardId(orderMessageDTO.getRewardId());
                        orderDetailDao.update(orderPO);
                    } else {
                        orderPO.setStatus(OrderStatus.FAILED);
                        orderDetailDao.update(orderPO);
                    }
                    break;
            }

        } catch (JsonProcessingException | TimeoutException e) {
            e.printStackTrace();
        }
    };

    @RabbitListener(
    		containerFactory="rabbitListenerContainerFactory",
    		queues="queue.order")
    public void handleMessage(@Payload Message message) throws IOException {
        log.info("handleMessage:messageBody:{}", new String(message.getBody()));

        OrderMessageDTO orderMessageDTO = objectMapper.readValue(message.getBody(),
                OrderMessageDTO.class);
        OrderDetailPO orderPO = orderDetailDao.selectOrder(orderMessageDTO.getOrderId());

        switch (orderPO.getStatus()) {

            case ORDER_CREATING: // 收到商家微服务发来的消息
                if (orderMessageDTO.getConfirmed() && null != orderMessageDTO.getPrice()) {
                    //更新订单状态，价格
                    orderPO.setStatus(OrderStatus.RESTAURANT_CONFIRMED);
                    orderPO.setPrice(orderMessageDTO.getPrice());
                    orderDetailDao.update(orderPO);

                    String messageToSend = objectMapper.writeValueAsString(orderMessageDTO);
                    rabbitTemplate.convertAndSend(
                            "exchange.order.deliveryman",
                            "key.deliveryman",
                            messageToSend);

                } else {
                    orderPO.setStatus(OrderStatus.FAILED);
                    orderDetailDao.update(orderPO);
                }
                break;
            case RESTAURANT_CONFIRMED: // 收到骑手微服务发来的消息
                if (null != orderMessageDTO.getDeliverymanId()) {
                    //更新订单状态，骑手id
                    orderPO.setStatus(OrderStatus.DELIVERYMAN_CONFIRMED);
                    orderPO.setDeliverymanId(orderMessageDTO.getDeliverymanId());
                    orderDetailDao.update(orderPO);

                    String messageToSend = objectMapper.writeValueAsString(orderMessageDTO);
                    rabbitTemplate.convertAndSend(
                            "exchange.order.settlement",
                            "key.settlement",
                            messageToSend);

                } else {
                    orderPO.setStatus(OrderStatus.FAILED);
                    orderDetailDao.update(orderPO);
                }
                break;
            case DELIVERYMAN_CONFIRMED: // 收到结算微服务发来的消息
                if (null != orderMessageDTO.getSettlementId()) {
                    //更新订单状态，结算id
                    orderPO.setStatus(OrderStatus.SETTLEMENT_CONFIRMED);
                    orderPO.setSettlementId(orderMessageDTO.getSettlementId());
                    orderDetailDao.update(orderPO);
                    String messageToSend = objectMapper.writeValueAsString(orderMessageDTO);
                    rabbitTemplate.convertAndSend(
                            "exchange.order.reward",
                            "key.reward",
                            messageToSend);
                } else {
                    orderPO.setStatus(OrderStatus.FAILED);
                    orderDetailDao.update(orderPO);
                }
                break;
            case SETTLEMENT_CONFIRMED: // 收到积分微服务发来的消息
                if (null != orderMessageDTO.getRewardId()) {
                    //更新订单状态，积分id
                    orderPO.setStatus(OrderStatus.ORDER_CREATED);
                    orderPO.setRewardId(orderMessageDTO.getRewardId());
                    orderDetailDao.update(orderPO);
                } else {
                    orderPO.setStatus(OrderStatus.FAILED);
                    orderDetailDao.update(orderPO);
                }
                break;
        }
    }
}
